<template>
  <div>
    <el-row :gutter="20" :style="{ width: width, height: height }">
      <el-col :span="12" style="height: 100%;">
        <vue-cropper
          ref="vueCropper"
          :img="options.img"
          :output-size="options.size"
          :output-type="options.outputType"
          :info="options.info"
          :can-scale="options.canScale"
          :auto-crop="options.autoCrop"
          :auto-crop-width="options.autoCropWidth"
          :auto-crop-height="options.autoCropHeight"
          :fixed="options.fixed"
          :fixed-number="options.fixedNumber"
          :full="options.full"
          :fixed-box="options.fixedBox"
          :can-move="options.canMove"
          :can-move-box="options.canMoveBox"
          :original="options.original"
          :center-box="options.centerBox"
          :high="options.high"
          :info-true="options.infoTrue"
          :max-img-size="options.maxImgSize"
          :enlarge="options.enlarge"
          :mode="options.mode"
          @realTime="realTime"
        />
      </el-col>
      <el-col :span="12" class="show_cropper">
        <div :style="previews.div" class="preview">
          <img v-if="previews" :src="previews.url" :style="previews.img">
        </div>
      </el-col>
    </el-row>
    <el-row :gutter="20" class="gl_pt_10">
      <el-col :span="12">
        <el-button type="primary" plain icon="el-icon-upload2" size="mini" style="position: relative;overflow: hidden;">
          <span>选择图片</span>
          <input type="file" accept="image/png, image/jpeg, image/jpg" class="upload_input" @change="chooseImg">
        </el-button>
        <el-tooltip class="item" effect="dark" placement="top">
          <div slot="content">放大</div>
          <el-button plain icon="el-icon-plus" size="mini" @click="changeScale(1)" />
        </el-tooltip>
        <el-tooltip class="item" effect="dark" placement="top">
          <div slot="content">缩小</div>
          <el-button plain icon="el-icon-minus" size="mini" @click="changeScale(-1)" />
        </el-tooltip>
        <el-tooltip class="item" effect="dark" placement="top">
          <div slot="content">逆时针</div>
          <el-button plain icon="el-icon-refresh-left" size="mini" @click="rotateLeft()" />
        </el-tooltip>
        <el-tooltip class="item" effect="dark" placement="top">
          <div slot="content">顺时针</div>
          <el-button plain icon="el-icon-refresh-right" size="mini" @click="rotateRight()" />
        </el-tooltip>
      </el-col>
      <el-col :span="12" align="center">
        <el-button type="primary" size="mini" @click="submitImg()">保存</el-button>
      </el-col>
    </el-row>
  </div>
</template>
<script>
import axios from 'axios';
import { getToken } from '@/lib/auth';
export default {
  name: 'PhotoCropper',
  props: {
    // 上传地址 - 完整的地址
    action: {
      type: String,
      required: true
    },
    // 裁剪配置参数 具体参数配置详见 https://github.com/xyxiao001/vue-cropper
    option: {
      type: Object,
      required: true
    },
    // 裁剪容器宽度
    width: {
      type: String,
      required: false,
      default: '100%'
    },
    // 裁剪容器高度
    height: {
      type: String,
      required: false,
      default: '375px'
    }
  },
  data() {
    return {
      options: {
        img: '', // 裁剪图片的地址
        outputSize: 1, // 裁剪生成图片的质量
        outputType: 'png', // 裁剪生成图片的格式
        info: true, // 裁剪框的大小信息
        canScale: true, // 图片是否允许滚轮缩放
        autoCrop: true, // 是否默认生成截图框
        autoCropWidth: '300px', // 默认生成截图框宽度
        autoCropHeight: '200px', // 默认生成截图框高度
        fixed: true, // 是否开启截图框宽高固定比例
        fixedNumber: [1.5, 1], // 截图框的宽高比例
        full: false, // 是否输出原图比例的截图
        fixedBox: true, // 固定截图框大小 不允许改变
        canMove: true, // 上传图片是否可以移动
        canMoveBox: true, // 截图框能否拖动
        original: true, // 上传图片按照原始比例渲染
        centerBox: false, // 截图框是否被限制在图片里面
        high: true, // 是否按照设备的dpr 输出等比例图片
        infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        maxImgSize: 2000, // 限制图片最大宽度和高度
        enlarge: 1, // 图片根据截图框输出比例倍数
        mode: '100% auto' // 图片默认渲染方式
      },
      tokenInfo: getToken(),
      // 预览
      previews: ''
    };
  },
  watch: {
    option: {
      handler() {
        this.initOption();
      },
      deep: true
    }
  },
  created() {
    this.initOption();
  },
  methods: {
    init() {
      this.file = null;
      this.options.img = '';
      this.cropperImg = null;
    },
    initOption() {
      for (const i in this.option) {
        if (i in this.options) {
          this.$set(this.options, i, this.option[i]);
        }
      }
    },
    // 选择图片
    chooseImg(e) {
      const file = e.target.files[0];
      const fileReader = new FileReader();
      fileReader.readAsDataURL(file);
      this.file = file;
      fileReader.onloadend = () => {
        this.options.img = fileReader.result;
      };
    },
    // 缩放
    changeScale(num) {
      num = num || 1;
      this.$refs.vueCropper.changeScale(num);
    },
    // 坐旋转
    rotateLeft() {
      this.$refs.vueCropper.rotateLeft();
    },
    // 右旋转
    rotateRight() {
      this.$refs.vueCropper.rotateRight();
    },
    // 保存
    submitImg() {
      this.$refs.vueCropper.getCropBlob(data => {
        const file = new window.File([data], this.file.name, { type: data.type });
        this.cropperImg = file;
        this.$emit('photoCropperSave', this.cropperImg);
      });
    },
    // 图片上传
    upload() {
      return new Promise((resolve, reject) => {
        if (!this.cropperImg) reject(new Error());
        const form = new FormData();
        form.append('formFile', this.cropperImg);
        this.uploadApi(this.action, form).then(res => {
          if (res.status === 200) {
            resolve(res.data);
          } else {
            reject(res.data);
          }
        });
      });
    },
    uploadApi(url, file) {
      const config = {
        headers: {
          Authorization: 'Bearer ' + this.tokenInfo
        }
      };
      return axios.post(url, file, config);
    },
    // 预览
    realTime(data) {
      this.previews = data;
    }
  }
};
</script>
<style>
.upload_input {
  position: absolute;
  top: 0;
  left: -100px;
  opacity: 0;
  width: calc(100% + 100px);
  height: 100%;
  cursor: pointer;
  overflow: hidden;
}
.show_cropper {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}
.preview {
  border: 1px solid #ddd;
  overflow: hidden;
}
</style>
